package com.nature.yanglegeyangultimate.ui;

import com.nature.yanglegeyangultimate.container.AllControlContainer;
import com.nature.yanglegeyangultimate.domain.Card;
import com.nature.yanglegeyangultimate.util.ReadResourcesUtil;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 整个游戏的主界面窗口，原来使用的是JPanel，现在修改使用JFrame作为尝试
 */
public class GameJFrame extends JFrame {

    //创建全局的JLayeredPane管理多层的JPanel
    private final JLayeredPane layeredPane = new JLayeredPane();

    //建立全局的卡牌容器对象
    private final AllControlContainer acc;

    //窗口的宽高
    private static final int WIDTH = 850;
    private static final int HEIGHT = 900;

    //背景颜色
    private static final Color BACKGROUND_COLOR = new Color(195, 254, 139);
    //背景图形颜色
    private static final Color SHAPE_COLOR = new Color(0, 0, 0);

    //大圆角矩形的配置信息
    //大圆角矩形的左上角坐标和宽高
    private static final int LARGE_RECT_X = 32; // 起始x坐标
    private static final int LARGE_RECT_Y = 660; // 起始y坐标，高度的1/4
    private static final int LARGE_RECT_WIDTH = WIDTH - 80; // 宽度与绿色边界相近
    private static final int LARGE_RECT_HEIGHT = HEIGHT / 6; // 高度为界面高度的1/4
    //大圆角矩形的颜色
    private static final Color LARGE_RECT_COLOR = new Color(139, 69, 19); // 土黄色
    //内部圆角矩形的颜色
    private static final Color INNER_RECT_COLOR = new Color(240, 230, 140);

    //设置卡牌的宽高
    private static final int CARD_WIDTH = 80;
    private static final int CARD_HEIGHT = 100;

    //牌区点击事件标记变量
    private static final int CARD_CENTER_FLAG = 1;
    private static final int CARD_LEFT_FLAG = 2;
    private static final int CARD_RIGHT_FLAG = 3;

    //设置背景的层级属性
    private static final int BACKGROUND_LEVEL = 1;
    //设置验卡区的层级属性
    private static final int CHECK_CARD_LEVEL = 2;
    //设置翻牌区的层级变量
    private static final int REVERSE_CARD_LEVEL = 3;


    public GameJFrame() {

        acc = new AllControlContainer();

        //初始化游戏界面
        initJFrame();

        //初始化游戏背景
        layeredPaneProperties();

        //设置界面组件
        initJMenuBar();

        //让界面展示
        this.setVisible(true);
    }

    //设置组件中心添加方法
    private void layeredPaneProperties() {

        this.getContentPane().removeAll();
        //清除所有组件
        layeredPane.removeAll();

        //配置游戏界面的背景属性
        layeredPane.add(initBackgroundJPanel(), Integer.valueOf(1));
        //添加验卡区的属性
        layeredPane.add(initCheckJPanel(), Integer.valueOf(2));

        //添加翻牌区的卡牌组件
        initCardReverse();

        //中心位置的卡牌摆放
        initCardCenter();

        //验卡区的卡牌摆放
        initCheckCard();

        //JPanel集中管理配置的基本属性怕配置
        layeredPane.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        layeredPane.setBounds(0, 0, WIDTH, HEIGHT);
        this.add(layeredPane);

        this.getContentPane().repaint();
    }

    //添加验卡区的卡牌组件
    private void initCheckCard() {

        //创建一个临时的list集合，用于展示卡牌
        java.util.List<Card> cards = new ArrayList<>();

        //获取验卡区的map对象
        java.util.Map<Integer, java.util.List<Card>> checkCardMap = acc.checkCardContainer.showCheckCardMap;
        //遍历获取每一个list
        for (java.util.List<Card> cardList : checkCardMap.values()) {
            //遍历当前等级的卡牌集合
            cards.addAll(cardList);
        }

        for (int i = 0; i < cards.size(); i++) {
            Card card = cards.get(i);
            card.setLevel(3);
            card.setXLeft(45 + 13 + i * (CARD_WIDTH + 10));
            card.setYUp(680);
            card.setBounds(45 + 13 + i * (CARD_WIDTH + 10), 680, CARD_WIDTH, CARD_HEIGHT);
        }

        // 添加到 layeredPane
        for (Card card : cards) {
            System.out.println(card);
            layeredPane.add(card, card.getLevel());
        }
    }


    //添加中央区的卡牌组件
    private void initCardCenter() {
        //获取中心牌盒的map集合对象
        for (int i : acc.centerCardContainer.centerCardMap.keySet()) {
            //获取当前等级的卡牌集合
            java.util.List<Card> cardList = acc.centerCardContainer.centerCardMap.get(i);
//            System.out.println("长度" + cardList.size() + "当前等级的卡牌集合：" + cardList);
            //遍历当前等级的卡牌集合
            for (Card c : cardList) {
                //设置卡牌坐标
                c.setBounds(c.getXLeft(), c.getYUp(), CARD_WIDTH, CARD_HEIGHT);
                //给卡牌添加层级属性
                layeredPane.add(c, Integer.valueOf(c.getLevel()));
                //检测当前卡牌对象上是否已经注册了鼠标点击事件，避免重复注册
                //todo 鼠标点击事件重复注册的后果就是会导致栈溢出和事件的重复提交和处理，会严重拖慢项目的效率
                if (c.getMouseListeners().length == 0) {
                    //添加鼠标点击事件
                    c.addMouseListener(new java.awt.event.MouseAdapter() {
                        @Override
                        public void mouseClicked(java.awt.event.MouseEvent evt) {
                            System.out.println("当前点击的是卡牌：" + JLayeredPane.getLayer(c));
                            //打印当前鼠标点击坐标
                            System.out.println("当前点击的坐标：" + evt.getX() + "," + evt.getY());

                            //获取当前点击的卡牌所在的层级
                            int level = JLayeredPane.getLayer(c);
                            //获取被点击对象
                            Card currentCard = (Card) evt.getSource();
                            System.out.println("当前要移除的卡牌+" + currentCard);

                            //传递参数用于控制容器的数据流转
                            boolean result = acc.cardTransfer(level, currentCard, CARD_CENTER_FLAG);
                            if (result) {
                                //要在组件加载容器中删除对应的组件
                                layeredPane.remove(currentCard);
                                layeredPaneProperties();
                                //单独开启一个线程播放点击音乐，单线程会影响画面的渲染
                                new Thread(ReadResourcesUtil::playAudioClick).start();
                            } else {
                               //游戏失败
                                new Thread(ReadResourcesUtil::playAudioFail).start();
                           }
                        }
                    });
                }
            }
        }
    }

    /**
     * 添加卡牌组件
     */
    private void initCardReverse() {
        //加载左边的卡牌
        processCards(acc.reverseCardContainer.cardLeft, CARD_LEFT_FLAG);
        //加载右边的卡牌
        processCards(acc.reverseCardContainer.cardRight, CARD_RIGHT_FLAG);
    }

    private void processCards(java.util.List<Card> cards, int flag) {
//        System.out.println("卡牌集合" + cards);
        //从最后一个元素开始遍历
        for (Card card : cards) {
            //获取当前要添加的卡牌对象
            //设置卡牌坐标
            card.setBounds(card.getXLeft(), card.getYUp(), CARD_WIDTH, CARD_HEIGHT);
            //添加层级属性
            layeredPane.add(card, Integer.valueOf(REVERSE_CARD_LEVEL));
            //添加鼠标点击事件
            if (card.getMouseListeners().length == 0) {
                card.addMouseListener(new java.awt.event.MouseAdapter() {
                    @Override
                    public void mouseClicked(java.awt.event.MouseEvent evt) {
                        System.out.println("当前点击的是卡牌：" + JLayeredPane.getLayer(card));
                        //打印当前鼠标点击坐标
                        System.out.println("当前点击的坐标：" + evt.getX() + "," + evt.getY());

                        //获取当前点击的卡牌所在的层级
                        int level = JLayeredPane.getLayer(card);
                        //获取被点击对象
                        Card currentCard = (Card) evt.getSource();
//                        System.out.println("当前要移除的卡牌+" + currentCard);

                        //传递参数用于控制容器的数据流转
                        boolean result = acc.cardTransfer(level, currentCard, flag);
                        if (result) {
                            // 要在组件加载容器中删除对应的组件
                            layeredPane.remove(card);
                            layeredPaneProperties();
                            // 单独开启一个线程播放点击音乐，单线程会影响画面的渲染
                            new Thread(ReadResourcesUtil::playAudioClick).start();
                        } else {
                            //游戏失败
                            new Thread(ReadResourcesUtil::playAudioFail).start();
                       }
                    }
                });
            }
        }
    }


    /**
     * 配置验卡区的背景和层级
     *
     * @return 返回验卡区的界面组件
     */
    private JPanel initCheckJPanel() {
        JPanel checkPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                drawLargeRoundedRect(g2d);
            }
        };

        //设置组件透明，能扣看见下面的背景
        checkPanel.setOpaque(false);

        //设置坐标
        checkPanel.setBounds(LARGE_RECT_X, LARGE_RECT_Y, 800, 200);

        //添加鼠标点击事件
        checkPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.out.println("鼠标点击了验卡区:" + JLayeredPane.getLayer(checkPanel));
            }
        });

        return checkPanel;
    }

    /**
     * 在背景上绘制大圆角矩形
     *
     * @param g2d 绘制图形的对象
     */
    private void drawLargeRoundedRect(Graphics2D g2d) {
        g2d.setColor(LARGE_RECT_COLOR); // 设置大圆角矩形的颜色为土黄色
        int x = 0; // 起始x坐标
        int y = 0; // 起始y坐标，高度的1/4
        int width = LARGE_RECT_WIDTH; // 宽度与绿色边界相近
        int height = LARGE_RECT_HEIGHT; // 高度为界面高度的1/4
        g2d.fillRoundRect(x, y, width, height, 20, 20); // 填充圆角矩形

        // 绘制小圆角矩形
        g2d.setColor(INNER_RECT_COLOR); // 设置小圆角矩形的颜色为亮黄色
        int innerX = x + 10; // 内部圆角矩形的起始x坐标
        int innerY = y + 10; // 内部圆角矩形的起始y坐标
        int innerWidth = width - 20; // 内部圆角矩形的宽度
        int innerHeight = height - 20; // 内部圆角矩形的高度
        g2d.fillRoundRect(innerX, innerY, innerWidth, innerHeight, 20, 20); // 填充内部圆角矩形
    }


    /**
     * 初始化背景JPanel
     *
     * @return 背景组件对象
     */
    private JPanel initBackgroundJPanel() {
        JPanel backgroundJPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                drawShapes(g2d);
            }
        };

        backgroundJPanel.setBackground(BACKGROUND_COLOR);
        // 设置边框
        backgroundJPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        // 没有设置布局的时候要自己设置组件的位置
        backgroundJPanel.setBounds(20, 20, WIDTH - 60, HEIGHT - 100);

        // 给组件添加鼠标点击事件
        backgroundJPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.out.println("鼠标点击了背景:" + JLayeredPane.getLayer(backgroundJPanel));
            }
        });
        return backgroundJPanel;
    }


    /**
     * 在背景上绘制图形信息
     *
     * @param g2d 绘制图形的对象
     */
    private void drawShapes(Graphics2D g2d) {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        g2d.setColor(SHAPE_COLOR); // 设置图形颜色为浅绿色

        // 随机绘制100个图形
        for (int i = 0; i < 300; i++) {
            int x = random.nextInt(getWidth());
            int y = random.nextInt(getHeight());
            int width = random.nextInt(20) + 5; // 宽度在5到25之间
            int height = random.nextInt(20) + 5; // 高度在5到25之间

            // 随机选择绘制椭圆、矩形或圆角矩形
            int shapeType = random.nextInt(3);
            switch (shapeType) {
                case 0:
                    g2d.drawOval(x, y, width, height); // 绘制椭圆边框
                    break;
                case 1:
                    g2d.drawRect(x, y, width, height); // 绘制矩形边框
                    break;
                case 2:
                    g2d.drawRoundRect(x, y, width, height, 10, 10); // 绘制圆角矩形边框
                    break;
            }
        }
    }


    /**
     * 初始化功能区组件
     */
    private void initJMenuBar() {
        //创建一些界面的基本组件
        JMenuBar jMenuBar = new JMenuBar();

        //创建两个选项组件
        JMenu function = new JMenu("功能");
        JMenu aboutUs = new JMenu("关于开发者");

        //创建每个小选项组件下的功能选项

        //更换图片选项功能
        JMenu changePicture = new JMenu("更换图片");

        jMenuBar.add(function);
        jMenuBar.add(aboutUs);
        jMenuBar.add(changePicture);

        this.setJMenuBar(jMenuBar);
    }

    /**
     * 初始化游戏界面
     */
    private void initJFrame() {
        //设置界面的宽高
        this.setSize(WIDTH, HEIGHT);
        //设置界面的标题
        this.setTitle("yang-le-ge-yang v1.0");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        //关闭模式一共有四种状态，可以根据需要进行自己的选择
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //解除界面默认的居中布局设置
        this.setLayout(null);
    }

}
